package com.gitee.cirnochat.common.exception;


import com.gitee.cirnochat.common.model.enums.ErrorCode;
import com.gitee.cirnochat.common.model.vo.resp.Result;
import io.swagger.v3.oas.annotations.Hidden;
import jakarta.servlet.ServletException;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.resource.NoResourceFoundException;

/**
 * 全局异常处理
 */
@RestControllerAdvice
@Hidden
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 处理请求参数校验失败异常
     */
    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    public Result<Void> handleValidationException(Exception e) {
        String message = "参数错误";
        if (e instanceof MethodArgumentNotValidException) {
            message = ((MethodArgumentNotValidException) e).getBindingResult().getFieldError().getDefaultMessage();
        } else if (e instanceof BindException) {
            message = ((BindException) e).getBindingResult().getFieldError().getDefaultMessage();
        }
        log.error("参数错误: {}", message);
        return Result.error(ErrorCode.PARAMS_ERROR, message);
    }

    @ExceptionHandler(TokenExpiredException.class)
    public Result<Void> handleTokenExpiredException(TokenExpiredException e) {
        log.error("Token 过期", e);
        return Result.error(ErrorCode.TOKEN_EXPIRED, e.getMessage());
    }

    /**
     * 处理资源未找到异常
     */
    @ExceptionHandler(NoResourceFoundException.class)
    public Result<Void> handleNoResourceFoundException(NoResourceFoundException e) {
        log.error("资源未找到", e);
        return Result.error(ErrorCode.NOT_FOUND_ERROR, ErrorCode.NOT_FOUND_ERROR.getMessage());
    }

    /**
     * 处理单个参数校验失败异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result<Void> handleConstraintViolationException(ConstraintViolationException e) {
        log.error("参数错误", e);
        return Result.error(ErrorCode.PARAMS_ERROR, e.getMessage());
    }

    /**
     * 处理通用业务异常
     */
    @ExceptionHandler(BusinessException.class)
    public Result<Void> handleBusinessException(BusinessException e) {
        log.error("业务异常", e);
        return Result.error(e.getCode(), e.getMessage());
    }

    /**
     * 处理运行时错误
     */
    @ExceptionHandler(RuntimeException.class)
    public Result<Void> handleRuntimeException(RuntimeException e) {
        log.error("运行时错误", e);
        return Result.error(ErrorCode.SYSTEM_ERROR, e.getMessage());
    }

    /**
     * 处理未知异常
     */
    @ExceptionHandler(Exception.class)
    public Result<Void> handleException(Exception e) {
        log.error("未知异常", e);
        return Result.error(ErrorCode.SYSTEM_ERROR, e.getMessage());
    }

    @ExceptionHandler(ServletException.class)
    public Result<Void> handleServletException(ServletException e) {
        log.error("Servlet异常", e);
        return Result.error(ErrorCode.SYSTEM_ERROR, e.getMessage());
    }
}
